package gee

import (
	"log"
	"net/http"
	"strings"
)

type (
	// 引擎，整个web服务的入口
	Engine struct {
		// 引擎默认是一个根路由组
		*RouteGroup
		// 路由映射，用于保存路由和处理函数之间的映射关系
		router *router
		// 用于拦截请求时，获取url路径上的中间件
		groups []*RouteGroup
	}
	// 路由组
	RouteGroup struct {
		// 每个路由组 都需要 有指向引擎的指针，因为后续路由组添加路由时需要调用引擎添加路由映射
		engine *Engine
		// 路由组前缀
		prefix string
		// 路由组的中间件
		middlewares []HandlerFunc
	}
)

func Default() *Engine {
	engine := New()
	// 全局路由组加上中间件
	engine.Use(Logger(), Recovery())
	return engine
}

// 处理http请求的入口
func (e *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// 需要拦截本次http请求的中间件
	var middlewares []HandlerFunc
	for _, group := range e.groups {
		if strings.HasPrefix(req.URL.Path, group.prefix) {
			middlewares = append(middlewares, group.middlewares...)
		}
	}
	c := newContext(w, req)
	c.handlers = middlewares
	// 处理中间件链路
	e.router.handle(c)
}

func New() *Engine {
	e := &Engine{router: newRouter()}
	e.RouteGroup = &RouteGroup{engine: e}
	e.groups = []*RouteGroup{e.RouteGroup}
	return e
}

func (g *RouteGroup) Use(middlewares ...HandlerFunc) {
	// 给路由组添加中间件
	g.middlewares = append(g.middlewares, middlewares...)
}

func (g *RouteGroup) Group(prefix string) *RouteGroup {
	// 创建新的路由组
	engine := g.engine
	newGroup := &RouteGroup{
		engine: engine,
		// 基于父路由
		prefix: g.prefix + prefix,
	}
	engine.groups = append(engine.groups, newGroup)
	return newGroup
}

// 添加路由
func (g *RouteGroup) addRoute(method string, comp string, handler HandlerFunc) {
	pattern := g.prefix + comp
	log.Printf("Route %4s - %s", method, pattern)
	g.engine.router.addRoute(method, pattern, handler)
}

func (g *RouteGroup) GET(pattern string, handler HandlerFunc) {
	g.addRoute("GET", pattern, handler)
}

func (g *RouteGroup) POST(pattern string, handler HandlerFunc) {
	g.addRoute("POST", pattern, handler)
}

func (e *Engine) Run(addr string) (err error) {
	return http.ListenAndServe(addr, e)
}
